home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 5
/
Aminet 5 - March 1995.iso
/
Aminet
/
misc
/
emu
/
Frodo.lha
/
src
/
6526.asm
< prev
next >
Wrap
Assembly Source File
|
1995-01-25
|
23KB
|
1,228 lines
*
* 6526.asm - CIA-Emulation
*
* Copyright (C) 1994-1995 by Christian Bauer
*
*
* Anmerkungen:
* ------------
*
* Funktionsweise/Periodic:
* - Für jede (simulierte) C64-Rasterzeile wird vom 6510-Task die Routine
* Periodic6526 aufgerufen, die die Timer herunterzählt, ggf. Interrupts
* auslöst und die Joysticks abfragt
*
* Timer/Latches:
* - Die Bytefolge im Register-File ist gegenüber dem echten 6526 umgekehrt,
* das wird aber bei den WriteTo6526- und ReadFrom6526-Routinen wieder
* ausgeglichen
*
* TOD-Clocks:
* - Die TODs werden synchron mit dem VBlank gezählt. Es wird also ein
* 50Hz-Eingangssignal simuliert.
*
* Tastaturabfrage:
* - Das Feld KeyMatrix enthält für jede Taste entsprechend der C64-
* Tastaturmatrix ein Bit (0: Taste gedrückt, 1: Taste nicht gedrückt)
* - Bei Lesezugriffen aus CIA-A, Port B werden entsprechend der aktiven
* (ausgewählten) Zeilen der Tastatur die entsprechenden Bits aus der
* Tastaturmatrix zusammengestellt
* - Die Help-Taste löst einen NMI aus (Restore), F10 einen RESET,
* über F9 wird das Einstellungs-Fenster aufgerufen
*
* Inkompatibilitäten:
* - Die TOD-Clock sollte bei einem Lesezugriff nicht angehalten,
* sondern gelatcht werden
*
MACHINE 68020
XREF ShowPrefs ;Main.asm
XREF _ciaaprb
XREF _ciaaddrb
XREF IntIsRESET ;6510.asm
XREF IntIsNMI
XREF IntIsCIAIRQ
XREF Peri6526Cont
XREF ChangedVA ;6569.asm
XREF Reset6581 ;6581.asm
XREF IECIsOpen ;1541.asm
XDEF Reset6526
XDEF ReadFrom6526A
XDEF ReadFrom6526B
XDEF WriteTo6526A
XDEF WriteTo6526B
XDEF Periodic6526
XDEF ChangedKeys
XDEF CountTODs
XDEF KeyPressed
XDEF CIACycles ;Prefs
XDEF Joystick1On
XDEF Joystick2On
XDEF JoystickSwap
XDEF KeyboardYZ
SECTION "CODE",CODE
**
** Definitionen
**
; CIA-Register
PRA = 0
PRB = 1
DDRA = 2
DDRB = 3
TAHI = 4 ;Timer-Wert A
TALO = 5 ;Achtung: Umgekehrte Bytefolge!
TBHI = 6 ;Timer-Wert B
TBLO = 7
TOD10THS = 8
TODSEC = 9
TODMIN = 10
TODHR = 11
SDR = 12
ICR = 13 ;Interrupt-Data
CRA = 14
CRB = 15
; Zusätzliche Register
LTCHA = 16 ;Timer-Latch A
LTCHB = 18 ;Timer-Latch B
INTMASK = 20 ;Interrupt-Enable
TODHALT = 21 ;TOD zwecks Beschreiben/Auslesen gestoppt
ALM10THS = 22 ;Alarmzeit
ALMSEC = 23
ALMMIN = 24
ALMHR = 25
TODDIV = 26 ;TOD-Frequenzteiler
TACNTPHI2 = 27 ;Timer A läuft und zählt Phi2
TBCNTPHI2 = 28 ;Timer B läuft und zählt Phi2
TBCNTTA = 29 ;Timer B läuft und zählt Unterläufe von Timer A
JOY1 = 30 ;Joystick 1 AND-Wert (nur CIA-A)
JOY2 = 31 ;Joystick 2 AND-Wert (nur CIA-A)
**
** CIAs zurücksetzen
**
; CIA-A
Reset6526 lea Registers1,a0
clr.l (a0)
clr.l 4(a0)
clr.l 8(a0)
clr.l 12(a0)
move.w #-1,TAHI(a0) ;Timer auf -1
move.w #-1,TBHI(a0)
move.w #$0001,LTCHA(a0) ;Latches auf 1
move.w #$0001,LTCHB(a0)
clr.b INTMASK(a0) ;Interrupts abschalten
clr.b TODHALT(a0) ;TOD läuft
clr.l ALM10THS(a0) ;Alarmzeit auf 00:00:00.0
clr.w TACNTPHI2(a0) ;Beide Timer anhalten
move.b #$ff,JOY1(a0) ;Joystick inaktiv
move.b #$ff,JOY2(a0)
; CIA-B
lea Registers2,a0
clr.l (a0)
clr.l 4(a0)
clr.l 8(a0)
clr.l 12(a0)
move.w #-1,TAHI(a0) ;Timer auf -1
move.w #-1,TBHI(a0)
move.w #$0001,LTCHA(a0) ;Latches auf 1
move.w #$0001,LTCHB(a0)
clr.b INTMASK(a0) ;Interrupts abschalten
clr.b TODHALT(a0) ;TOD läuft
clr.l ALM10THS(a0) ;Alarmzeit auf 00:00:00.0
clr.w TACNTPHI2(a0) ;Beide Timer anhalten
; Tastaturmatrix löschen
moveq #-1,d0
move.l d0,KeyMatrix
move.l d0,KeyMatrix+4
; VIC-Bank 0 einstellen
moveq #0,d0
bra ChangedVA
**
** Tastaturbelegung geändert, Y und Z sortieren
**
ChangedKeys tst.w KeyboardYZ
bne 1$
move.l #$00010004,KeyPatch1
move.l #$00030001,KeyPatch2
rts
1$ move.l #$00030001,KeyPatch1
move.l #$00010004,KeyPatch2
rts
**
** In ein CIA-A-Register schreiben
** d0.w: Registernummer ($00-$0f)
** d1.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
**
WriteTo6526A lea Registers1,a0
move.l WriteTabA(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
WriteTabA dc.l WrNormal
dc.l WrNormal
dc.l WrNormal
dc.l WrNormal
dc.l WrTALO
dc.l WrTAHI
dc.l WrTBLO
dc.l WrTBHI
dc.l WrTOD10THS
dc.l WrTODSEC
dc.l WrTODMIN
dc.l WrTODHR
dc.l WrNormal
dc.l WrICR
dc.l WrCRA
dc.l WrCRB
WrNormal move.b d1,(a0,d0.w)
rts
WrTALO move.b d1,LTCHA+1(a0)
rts
WrTAHI move.b d1,LTCHA(a0)
btst #0,CRA(a0) ;Timer A gestoppt?
bne 1$
move.w LTCHA(a0),TAHI(a0) ;Ja, Timer laden
1$ rts
WrTBLO move.b d1,LTCHB+1(a0)
rts
WrTBHI move.b d1,LTCHB(a0)
btst #0,CRB(a0) ;Timer B gestoppt?
bne 1$
move.w LTCHB(a0),TBHI(a0) ;Ja, Timer laden
1$ rts
WrTOD10THS and.b #$0f,d1
clr.b TODHALT(a0) ;TOD weiterlaufen lassen
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TOD10THS(a0)
rts
1$ move.b d1,ALM10THS(a0)
rts
WrTODSEC and.b #$7f,d1
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TODSEC(a0)
rts
1$ move.b d1,ALMSEC(a0)
rts
WrTODMIN and.b #$7f,d1
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TODMIN(a0)
rts
1$ move.b d1,ALMMIN(a0)
rts
WrTODHR and.b #$9f,d1
st.b TODHALT(a0) ;TOD anhalten
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TODHR(a0)
rts
1$ move.b d1,ALMHR(a0)
rts
WrICR bclr #7,d1 ;S/C-Bit löschen
bne 1$ ;War es gesetzt?
not.b d1 ;Nein, Bits zum Löschen negieren
and.b d1,INTMASK(a0) ;Und Bits löschen
bra 2$
1$ or.b d1,INTMASK(a0) ;Bits setzen
2$ rts
WrCRA btst #4,d1 ;Force load?
beq 1$
and.b #$ef,d1
move.w LTCHA(a0),TAHI(a0) ;Ja, Timer laden
1$ move.b d1,CRA(a0)
and.b #$21,d1 ;Läuft der Timer und zählt er Phi2?
cmp.b #$01,d1
seq.b TACNTPHI2(a0) ;Ja, Flag setzen
rts
WrCRB btst #4,d1 ;Force load?
beq 1$
and.b #$ef,d1
move.w LTCHB(a0),TBHI(a0) ;Ja, Timer laden
1$ move.b d1,CRB(a0)
and.b #$61,d1 ;Läuft der Timer und zählt er Phi2?
cmp.b #$01,d1
seq.b TBCNTPHI2(a0) ;Ja, Flag setzen
cmp.b #$41,d1 ;Läuft er und zählt Unterläuft von Timer A?
seq.b TBCNTTA(a0) ;Ja, Flag setzen
rts
**
** In ein CIA-B-Register schreiben
** d0.w: Registernummer ($00-$0f)
** d1.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
**
WriteTo6526B lea Registers2,a0
move.l WriteTabB(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
WriteTabB dc.l WrBPRA
dc.l WrNormal
dc.l WrBDDRA
dc.l WrNormal
dc.l WrTALO
dc.l WrTAHI
dc.l WrTBLO
dc.l WrTBHI
dc.l WrTOD10THS
dc.l WrTODSEC
dc.l WrTODMIN
dc.l WrTODHR
dc.l WrNormal
dc.l WrICR
dc.l WrCRA
dc.l WrCRB
WrBPRA move.b d1,PRA(a0) ;Floppy/VA
tst.b IECIsOpen ;Wenn IEC aktiv ist, Port setzen
beq WrBNewVA
move.b d1,_ciaaprb
bra WrBNewVA
WrBDDRA move.b d1,DDRA(a0) ;Floppy/VA
tst.b IECIsOpen ;Wenn IEC aktiv ist, DDR setzen
beq WrBNewVA
move.b d1,_ciaaddrb
WrBNewVA move.b DDRA(a0),d0 ;VA extrahieren
not.b d0
or.b PRA(a0),d0
not.b d0
and.b #$03,d0
bra ChangedVA ;Und dem VIC mitteilen
**
** Aus einem CIA-A-Register lesen
** d0.w: Registernummer ($00-$0f)
** Rückgabe: d0.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
** Darf a1 nicht verändern!
**
ReadFrom6526A move.l ReadTabA(pc,d0.w*4),a0
jmp (a0)
CNOP 0,4
ReadTabA dc.l RdAPRA
dc.l RdAPRB
dc.l RdANormal
dc.l RdANormal
dc.l RdATALO
dc.l RdATAHI
dc.l RdATBLO
dc.l RdATBHI
dc.l RdATOD10THS
dc.l RdANormal
dc.l RdANormal
dc.l RdATODHR
dc.l RdANormal
dc.l RdAICR
dc.l RdANormal
dc.l RdANormal
RdANormal lea Registers1,a0
move.b (a0,d0.w),d0
rts
RdAPRA lea Registers1,a0
move.b DDRA(a0),d0
not.b d0
or.b PRA(a0),d0
and.b JOY2(a0),d0
rts
RdAPRB move.l a1,-(sp)
lea Registers1,a0
lea KeyMatrix,a1
move.b PRA(a0),d1 ;Tastaturabfrage
move.b #$ff,d0 ;Alle aktiven Reihen dazuANDen
lsr.b #1,d1
bcs 1$
and.b (a1),d0
1$ lsr.b #1,d1
bcs 2$
and.b 1(a1),d0
2$ lsr.b #1,d1
bcs 3$
and.b 2(a1),d0
3$ lsr.b #1,d1
bcs 4$
and.b 3(a1),d0
4$ lsr.b #1,d1
bcs 5$
and.b 4(a1),d0
5$ lsr.b #1,d1
bcs 6$
and.b 5(a1),d0
6$ lsr.b #1,d1
bcs 7$
and.b 6(a1),d0
7$ lsr.b #1,d1
bcs 8$
and.b 7(a1),d0
8$ and.b JOY1(a0),d0
move.b DDRB(a0),d1
not.b d1
or.b PRB(a0),d1
and.b d1,d0
move.l (sp)+,a1
rts
RdATALO move.b Registers1+TALO,d0 ;Weil die Timer im Registerfile
rts ;als big-endian gespeichert sind
RdATAHI move.b Registers1+TAHI,d0
rts
RdATBLO move.b Registers1+TBLO,d0
rts
RdATBHI move.b Registers1+TBHI,d0
rts
RdATOD10THS lea Registers1,a0
move.b TOD10THS(a0),d0
clr.b TODHALT(a0) ;TOD weiterlaufen lassen
rts
RdATODHR lea Registers1,a0
st.b TODHALT(a0) ;TOD anhalten
move.b TODHR(a0),d0
rts
RdAICR lea Registers1,a0
move.b ICR(a0),d0 ;ICR beim Lesen löschen
clr.b ICR(a0)
clr.b IntIsCIAIRQ ;IRQ zurücknehmen
rts
**
** Aus einem CIA-B-Register lesen
** d0.w: Registernummer ($00-$0f)
** Rückgabe: d0.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
** Darf a1 nicht verändern!
**
ReadFrom6526B move.l ReadTabB(pc,d0.w*4),a0
jmp (a0)
CNOP 0,4
ReadTabB dc.l RdBPRA
dc.l RdBPRB
dc.l RdBNormal
dc.l RdBNormal
dc.l RdBTALO
dc.l RdBTAHI
dc.l RdBTBLO
dc.l RdBTBHI
dc.l RdBTOD10THS
dc.l RdBNormal
dc.l RdBNormal
dc.l RdBTODHR
dc.l RdBNormal
dc.l RdBICR
dc.l RdBNormal
dc.l RdBNormal
RdBNormal lea Registers2,a0
move.b (a0,d0.w),d0
rts
RdBPRA lea Registers2,a0
move.b DDRA(a0),d0 ;Floppy/VA
not.b d0
or.b PRA(a0),d0
tst.b IECIsOpen ;Wenn IEC aktiv ist, davon lesen
beq 1$
and.b #$03,d0
move.b _ciaaprb,d1
and.b #$fc,d1
or.b d1,d0
1$ rts
RdBPRB lea Registers2,a0
move.b DDRB(a0),d0 ;Userport
not.b d0 ;Eingabebits immer 1
or.b PRB(a0),d0
rts
RdBTALO move.b Registers2+TALO,d0 ;Weil die Timer im Registerfile
rts ;als big-endian gespeichert sind
RdBTAHI move.b Registers2+TAHI,d0
rts
RdBTBLO move.b Registers2+TBLO,d0
rts
RdBTBHI move.b Registers2+TBHI,d0
rts
RdBTOD10THS lea Registers2,a0
move.b TOD10THS(a0),d0
clr.b TODHALT(a0) ;TOD weiterlaufen lassen
rts
RdBTODHR lea Registers2,a0
st.b TODHALT(a0) ;TOD anhalten
move.b TODHR(a0),d0
rts
RdBICR lea Registers2,a0
move.b ICR(a0),d0 ;ICR beim Lesen löschen
clr.b ICR(a0)
rts
**
** Wird jede Rasterzeile einmal aufgerufen
**
*
* CIA-A
* d1: ICR
* d2: INTMASK
* d3: CIACycles
*
Periodic6526 lea Registers1,a0
move.b ICR(a0),d1
move.b INTMASK(a0),d2
move.w CIACycles,d3
*
* Timer A
*
tst.b TACNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaATADone
sub.w d3,TAHI(a0) ;Ja, herabzählen
bcc CiaATADone ;Unterlauf?
or.b #$01,d1 ;Ja, IRQ-Bit setzen
btst #0,d2 ;IRQ freigegeben?
beq CiaATANoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
st.b IntIsCIAIRQ ;und IRQ auslösen
CiaATANoIRQ move.w LTCHA(a0),TAHI(a0) ;Zähler neu laden
btst #3,CRA(a0) ;One-Shot?
beq 1$
and.b #$fe,CRA(a0) ;Ja, Zähler stoppen
clr.b TACNTPHI2(a0)
1$ tst.b TBCNTTA(a0) ;Läuft Timer B und zählt er
beq CiaATADone ; Unterläufe von Timer A?
subq.w #1,TBHI(a0) ;Ja, Timer B runterzählen
bcs CiaATBUnderflow ;Untergelaufen?
CiaATADone
*
* Timer B
*
tst.b TBCNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaATBDone
sub.w d3,TBHI(a0) ;Ja, herabzählen
bcc CiaATBDone ;Unterlauf?
CiaATBUnderflow or.b #$02,d1 ;Ja, IRQ-Bit setzen
btst #1,d2 ;IRQ freigegeben?
beq CiaATBNoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
st.b IntIsCIAIRQ ;und IRQ auslösen
CiaATBNoIRQ move.w LTCHB(a0),TBHI(a0) ;Zähler neu laden
btst #3,CRB(a0) ;One-Shot?
beq CiaATBDone
and.b #$fe,CRB(a0) ;Ja, Zähler stoppen
clr.b TBCNTPHI2(a0)
clr.b TBCNTTA(a0)
CiaATBDone
*
* ICR zurückschreiben
*
move.b d1,ICR(a0)
*
* CIA-B
* d1: ICR
* d2: INTMASK
* d3: CIACycles
*
lea Registers2,a0
move.b ICR(a0),d1
move.b INTMASK(a0),d2
*
* Timer A
*
tst.b TACNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaBTADone
sub.w d3,TAHI(a0) ;Ja, herabzählen
bcc CiaBTADone ;Unterlauf?
or.b #$01,d1 ;Ja, IRQ-Bit setzen
btst #0,d2 ;IRQ freigegeben?
beq CiaBTANoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
st.b IntIsNMI ;und NMI auslösen
CiaBTANoIRQ move.w LTCHA(a0),TAHI(a0) ;Zähler neu laden
btst #3,CRA(a0) ;One-Shot?
beq 1$
and.b #$fe,CRA(a0) ;Ja, Zähler stoppen
clr.b TACNTPHI2(a0)
1$ tst.b TBCNTTA(a0) ;Läuft Timer B und zählt er
beq CiaBTADone ; Unterläufe von Timer A?
subq.w #1,TBHI(a0) ;Ja, Timer B runterzählen
bcs CiaBTBUnderflow ;Untergelaufen?
CiaBTADone
*
* Timer B
*
tst.b TBCNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaBTBDone
sub.w d3,TBHI(a0) ;Ja, herabzählen
bcc CiaBTBDone ;Unterlauf?
CiaBTBUnderflow or.b #$02,d1 ;Ja, IRQ-Bit setzen
btst #1,d2 ;IRQ freigegeben?
beq CiaBTBNoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
st.b IntIsNMI ;und NMI auslösen
CiaBTBNoIRQ move.w LTCHB(a0),TBHI(a0) ;Zähler neu laden
btst #3,CRB(a0) ;One-Shot?
beq CiaBTBDone
and.b #$fe,CRB(a0) ;Ja, Zähler stoppen
clr.b TBCNTPHI2(a0)
clr.b TBCNTTA(a0)
CiaBTBDone
*
* ICR zurückschreiben
*
move.b d1,ICR(a0)
*
* Joystickabfrage
*
lea Registers1,a0
; Port 1
move.b #$ff,d2 ;Vorgabe: Joystick inaktiv
tst.w Joystick1On(pc)
beq 15$
btst #6,$bfe001 ;Feuerknopf
bne 11$
bclr #4,d2
11$ move.w $dff00a,d0
btst #1,d0 ;Rechts
beq 12$
bclr #3,d2
12$ btst #9,d0 ;Links
beq 13$
bclr #2,d2
13$ move.w d0,d1
add.w d0,d0
eor.w d1,d0
btst #1,d0 ;Runter
beq 14$
bclr #1,d2
14$ btst #9,d0 ;Hoch
beq 15$
bclr #0,d2
15$ move.b d2,JOY1(a0)
; Port 2
move.b #$ff,d2 ;Vorgabe: Joystick inaktiv
tst.w Joystick2On(pc)
beq 25$
btst #7,$bfe001 ;Feuerknopf
bne 21$
bclr #4,d2
21$ move.w $dff00c,d0
btst #1,d0 ;Rechts
beq 22$
bclr #3,d2
22$ btst #9,d0 ;Links
beq 23$
bclr #2,d2
23$ move.w d0,d1
add.w d0,d0
eor.w d1,d0
btst #1,d0 ;Runter
beq 24$
bclr #1,d2
24$ btst #9,d0 ;Hoch
beq 25$
bclr #0,d2
25$ move.b d2,JOY2(a0)
; Joysticks vertauschen?
tst.w JoystickSwap(pc)
beq 30$
move.b JOY1(a0),d0
move.b JOY2(a0),JOY1(a0)
move.b d0,JOY2(a0)
; In 6510-Task zurückspringen
30$ bra Peri6526Cont
**
** TODs zählen
**
*
* CIA-A
*
CountTODs lea Registers1,a0
subq.b #1,TODDIV(a0) ;Frequenzteiler herabzählen
bpl CiaATODNop
btst #7,CRA(a0) ;Untergelaufen,
beq CiaATOD60Hz ; je nach 50/60Hz-Flag neu laden
move.b #4,TODDIV(a0)
bra CiaATODLoaded
CiaATOD60Hz move.b #5,TODDIV(a0)
CiaATODLoaded move #0,ccr ;X löschen
move.b #1,d0 ;1/10 Sekunden erhöhen
move.b TOD10THS(a0),d1
abcd d0,d1
move.b d1,TOD10THS(a0)
cmp.b #$10,d1 ;Über 10?
blo CiaATODDone
clr.b TOD10THS(a0) ;Ja, 1/10 Sekunden auf Null setzen
move #0,ccr ;und Sekunden erhöhen
move.b #1,d0
move.b TODSEC(a0),d1
abcd d0,d1
move.b d1,TODSEC(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaATODDone
clr.b TODSEC(a0) ;Ja, Sekunden auf Null setzen
move #0,ccr ;und Minuten erhöhen
move.b #1,d0
move.b TODMIN(a0),d1
abcd d0,d1
move.b d1,TODMIN(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaATODDone
clr.b TODMIN(a0) ;Ja, Minuten auf Null setzen
move #0,ccr ;und Stunden erhöhen
move.b #1,d0
move.b TODHR(a0),d1
and.b #$1f,d1 ;AM/PM ausmaskieren
abcd d0,d1
and.b #$80,TODHR(a0) ;Stunden schreiben, AM/PM lassen
or.b d1,TODHR(a0)
cmp.b #$12,d1 ;Über 12?
blo CiaATODDone
and.b #$1f,TODHR(a0) ;Ja, Stunden auf Null setzen
eor.b #$80,TODHR(a0) ;und AM/PM umdrehen
CiaATODDone move.l TOD10THS(a0),d0 ;Alarmzeit erreicht?
cmp.l ALM10THS(a0),d0
bne CiaATODNop
move.b ICR(a0),d0 ;Ja, IRQ-Bit setzen
or.b #$04,d0
btst #2,INTMASK(a0) ;IRQ freigegeben?
beq CiaATODNoIRQ
or.b #$80,d0 ;Ja, IR-Bit setzen
st.b IntIsCIAIRQ ;und IRQ auslösen
CiaATODNoIRQ move.b d0,ICR(a0)
CiaATODNop
*
* CIA-B
*
lea Registers2,a0
subq.b #1,TODDIV(a0) ;Frequenzteiler herabzählen
bpl CiaBTODNop
btst #7,CRA(a0) ;Untergelaufen,
beq CiaBTOD60Hz ; je nach 50/60Hz-Flag neu laden
move.b #4,TODDIV(a0)
bra CiaBTODLoaded
CiaBTOD60Hz move.b #5,TODDIV(a0)
CiaBTODLoaded move #0,ccr ;X löschen
move.b #1,d0 ;1/10 Sekunden erhöhen
move.b TOD10THS(a0),d1
abcd d0,d1
move.b d1,TOD10THS(a0)
cmp.b #$10,d1 ;Über 10?
blo CiaBTODDone
clr.b TOD10THS(a0) ;Ja, 1/10 Sekunden auf Null setzen
move #0,ccr ;und Sekunden erhöhen
move.b #1,d0
move.b TODSEC(a0),d1
abcd d0,d1
move.b d1,TODSEC(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaBTODDone
clr.b TODSEC(a0) ;Ja, Sekunden auf Null setzen
move #0,ccr ;und Minuten erhöhen
move.b #1,d0
move.b TODMIN(a0),d1
abcd d0,d1
move.b d1,TODMIN(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaBTODDone
clr.b TODMIN(a0) ;Ja, Minuten auf Null setzen
move #0,ccr ;und Stunden erhöhen
move.b #1,d0
move.b TODHR(a0),d1
and.b #$1f,d1 ;AM/PM ausmaskieren
abcd d0,d1
and.b #$80,TODHR(a0) ;Stunden schreiben, AM/PM lassen
or.b d1,TODHR(a0)
cmp.b #$12,d1 ;Über 12?
blo CiaBTODDone
and.b #$1f,TODHR(a0) ;Ja, Stunden auf Null setzen
eor.b #$80,TODHR(a0) ;und AM/PM umdrehen
CiaBTODDone move.l TOD10THS(a0),d0 ;Alarmzeit erreicht?
cmp.l ALM10THS(a0),d0
bne CiaBTODNop
move.b ICR(a0),d0 ;Ja, IRQ-Bit setzen
or.b #$04,d0
btst #2,INTMASK(a0) ;IRQ freigegeben?
beq CiaBTODNoIRQ
or.b #$80,d0 ;Ja, IR-Bit setzen
st.b IntIsNMI ;und NMI auslösen
CiaBTODNoIRQ move.b d0,ICR(a0)
CiaBTODNop rts
**
** Taste wurde gedrückt
** d0.b: RawKey-Code
**
KeyPressed lea KeyMatrix,a0
bclr #7,d0 ;KeyUp/KeyDown
bne 1$
cmp.b #$40,d0
bhs KeyDownSpecial
and.w #$003f,d0
movem.w KeyTable(pc,d0.w*4),d0/d1
bclr d1,(a0,d0.w)
rts
1$ cmp.b #$40,d0
bhs KeyUpSpecial
and.w #$003f,d0
movem.w KeyTable(pc,d0.w*4),d0/d1
bset d1,(a0,d0.w)
rts
; Die häßlichste Tastaturabfrage aller Zeiten...
KeyDownSpecial cmp.b #$5f,d0 ;Help -> Restore
beq KeyHelpD
cmp.b #$59,d0 ;F10 -> Reset
beq KeyF10D
cmp.b #$58,d0 ;F9 -> Prefs
beq KeyF9D
cmp.b #$40,d0 ;Space
beq KeySpaceD
cmp.b #$41,d0 ;Backspace -> DEL
beq KeyBackD
cmp.b #$44,d0 ;Return
beq KeyReturnD
cmp.b #$45,d0 ;Esc -> R/S
beq KeyEscD
cmp.b #$46,d0 ;Delete -> HOME
beq KeyDeleteD
cmp.b #$4c,d0 ;Crsr up -> Shift CUD
beq KeyUpD
cmp.b #$4d,d0 ;Crsr down -> CUD
beq KeyDownD
cmp.b #$4e,d0 ;Crsr right -> CLR
beq KeyRightD
cmp.b #$4f,d0 ;Crsr left -> Shift CLR
beq KeyLeftD
cmp.b #$50,d0 ;F1
beq KeyF1D
cmp.b #$51,d0 ;F2
beq KeyF2D
cmp.b #$52,d0 ;F3
beq KeyF3D
cmp.b #$53,d0 ;F4
beq KeyF4D
cmp.b #$54,d0 ;F5
beq KeyF5D
cmp.b #$55,d0 ;F6
beq KeyF6D
cmp.b #$56,d0 ;F7
beq KeyF7D
cmp.b #$57,d0 ;F8
beq KeyF8D
cmp.b #$60,d0 ;Shift links
beq KeyShiftLD
cmp.b #$61,d0 ;Shift rechts
beq KeyShiftRD
cmp.b #$62,d0 ;Caps -> SHL
beq KeyShiftLD
cmp.b #$63,d0 ;Ctrl
beq KeyCtrlD
cmp.b #$66,d0 ;Amiga links -> C=
beq KeyAmigaD
cmp.b #$67,d0 ;Amiga rechts -> C=
beq KeyAmigaD
rts
KeyUpSpecial cmp.b #$40,d0 ;Space
beq KeySpaceU
cmp.b #$41,d0 ;Backspace -> DEL
beq KeyBackU
cmp.b #$44,d0 ;Return
beq KeyReturnU
cmp.b #$45,d0 ;Esc -> R/S
beq KeyEscU
cmp.b #$46,d0 ;Delete -> HOME
beq KeyDeleteU
cmp.b #$4c,d0 ;Crsr up -> Shift CUD
beq KeyUpU
cmp.b #$4d,d0 ;Crsr down -> CUD
beq KeyDownU
cmp.b #$4e,d0 ;Crsr right -> CLR
beq KeyRightU
cmp.b #$4f,d0 ;Crsr up -> Shift CUD
beq KeyLeftU
cmp.b #$50,d0 ;F1
beq KeyF1U
cmp.b #$51,d0 ;F2
beq KeyF2U
cmp.b #$52,d0 ;F3
beq KeyF3U
cmp.b #$53,d0 ;F4
beq KeyF4U
cmp.b #$54,d0 ;F5
beq KeyF5U
cmp.b #$55,d0 ;F6
beq KeyF6U
cmp.b #$56,d0 ;F7
beq KeyF7U
cmp.b #$57,d0 ;F8
beq KeyF8U
cmp.b #$60,d0 ;Shift links
beq KeyShiftLU
cmp.b #$61,d0 ;Shift rechts
beq KeyShiftRU
cmp.b #$62,d0 ;Caps -> SHL
beq KeyShiftLU
cmp.b #$63,d0 ;Ctrl
beq KeyCtrlU
cmp.b #$66,d0 ;Amiga links -> C=
beq KeyAmigaU
cmp.b #$67,d0 ;Amiga rechts -> C=
beq KeyAmigaU
rts
KeyHelpD st.b IntIsNMI ;NMI auslösen
rts
KeyF10D st.b IntIsRESET ;6510-Reset
bsr Reset6526
bra Reset6581
KeyF9D jmp ShowPrefs
; Es folgt ein Alptraum. Bitte die Augen schließen.
KeySpaceD bclr #4,7(a0)
rts
KeySpaceU bset #4,7(a0)
rts
KeyBackD bclr #0,(a0)
rts
KeyBackU bset #0,(a0)
rts
KeyReturnD bclr #1,(a0)
rts
KeyReturnU bset #1,(a0)
rts
KeyEscD bclr #7,7(a0)
rts
KeyEscU bset #7,7(a0)
rts
KeyDeleteD bclr #3,6(a0)
rts
KeyDeleteU bset #3,6(a0)
rts
KeyUpD bclr #4,6(a0)
bclr #7,(a0)
rts
KeyUpU bset #4,6(a0)
bset #7,(a0)
rts
KeyDownD bclr #7,(a0)
rts
KeyDownU bset #7,(a0)
rts
KeyRightD bclr #2,(a0)
rts
KeyRightU bset #2,(a0)
rts
KeyLeftD bclr #4,6(a0)
bclr #2,(a0)
rts
KeyLeftU bset #4,6(a0)
bset #2,(a0)
rts
KeyF1D bclr #4,(a0)
rts
KeyF1U bset #4,(a0)
rts
KeyF3D bclr #5,(a0)
rts
KeyF3U bset #5,(a0)
rts
KeyF5D bclr #6,(a0)
rts
KeyF5U bset #6,(a0)
rts
KeyF7D bclr #3,(a0)
rts
KeyF7U bset #3,(a0)
rts
KeyF2D bclr #4,6(a0)
bclr #4,(a0)
rts
KeyF2U bset #4,6(a0)
bset #4,(a0)
rts
KeyF4D bclr #4,6(a0)
bclr #5,(a0)
rts
KeyF4U bset #4,6(a0)
bset #5,(a0)
rts
KeyF6D bclr #4,6(a0)
bclr #6,(a0)
rts
KeyF6U bset #4,6(a0)
bset #6,(a0)
rts
KeyF8D bclr #4,6(a0)
bclr #3,(a0)
rts
KeyF8U bset #4,6(a0)
bset #3,(a0)
rts
KeyShiftLD bclr #7,1(a0)
rts
KeyShiftLU bset #7,1(a0)
rts
KeyShiftRD bclr #4,6(a0)
rts
KeyShiftRU bset #4,6(a0)
rts
KeyCtrlD bclr #2,7(a0)
rts
KeyCtrlU bset #2,7(a0)
rts
KeyAmigaD bclr #5,7(a0)
rts
KeyAmigaU bset #5,7(a0)
rts
**
** Datenbereich
**
CNOP 0,4
Registers1 ds.b 32 ;CIA-A-Register
Registers2 ds.b 32 ;CIA-B-Register
CIACycles dc.w 0 ;Anzahl Phi2-Zyklen pro Rasterzeile (für Timer)
Joystick1On dc.w 0 ;Joystick an Port 1 wird abgefragt
Joystick2On dc.w 0 ;Joystick an Port 2 wird abgefragt
JoystickSwap dc.w 0 ;Joysticks vertauschen
KeyboardYZ dc.w 0 ;Amerikanische Tastaturbelegung
; Tastaturübersetzungstabelle:
; Für jeden Amiga-RawKey Spalte und Zeile in der KeyMatrix
CNOP 0,4
KeyTable dc.w 7,1 ;` -> <-
dc.w 7,0 ;1
dc.w 7,3 ;2
dc.w 1,0 ;3
dc.w 1,3 ;4
dc.w 2,0 ;5
dc.w 2,3 ;6
dc.w 3,0 ;7
dc.w 3,3 ;8
dc.w 4,0 ;9
dc.w 4,3 ;0
dc.w 5,0 ;ß -> +
dc.w 5,3 ;´ -> -
dc.w 6,0 ;\ -> £
dc.w 0,0
dc.w 4,3 ;NP 0
dc.w 7,6 ;Q
dc.w 1,1 ;W
dc.w 1,6 ;E
dc.w 2,1 ;R
dc.w 2,6 ;T
KeyPatch1 dc.w 1,4 ;Y -> Z
dc.w 3,6 ;U
dc.w 4,1 ;I
dc.w 4,6 ;O
dc.w 5,1 ;P
dc.w 5,6 ;ü -> @
dc.w 6,1 ;+ -> *
dc.w 0,0
dc.w 7,0 ;NP 1
dc.w 7,3 ;NP 2
dc.w 1,0 ;NP 3
dc.w 1,2 ;A
dc.w 1,5 ;S
dc.w 2,2 ;D
dc.w 2,5 ;F
dc.w 3,2 ;G
dc.w 3,5 ;H
dc.w 4,2 ;J
dc.w 4,5 ;K
dc.w 5,2 ;L
dc.w 5,5 ;ö -> :
dc.w 6,2 ;ä -> ;
dc.w 6,5 ;# -> =
dc.w 0,0
dc.w 1,3 ;NP 4
dc.w 2,0 ;NP 5
dc.w 2,3 ;NP 6
dc.w 6,6 ;< -> ^
KeyPatch2 dc.w 3,1 ;Z -> Y
dc.w 2,7 ;X
dc.w 2,4 ;C
dc.w 3,7 ;V
dc.w 3,4 ;B
dc.w 4,7 ;N
dc.w 4,4 ;M
dc.w 5,7 ;,
dc.w 5,4 ;.
dc.w 6,7 ;- -> /
dc.w 0,0
dc.w 0,0
dc.w 3,0 ;NP 7
dc.w 3,3 ;NP 8
dc.w 4,0 ;NP 9
; Bit 7 6 5 4 3 2 1 0
; 0 CUD F5 F3 F1 F7 CLR RET DEL
; 1 SHL E S Z 4 A W 3
; 2 X T F C 6 D R 5
; 3 V U H B 8 G Y 7
; 4 N O K M 0 J I 9
; 5 , @ : . - L P +
; 6 / ^ = SHR HOM ; * £
; 7 R/S Q C= SPC 2 CTL <- 1
KeyMatrix ds.b 8 ;C64-Tastaturmatrix pro Taste ein Bit
;0: Taste gedrückt
END